# -*- encoding:utf-8 -*-
"""文件，目录相关方法"""

import os
import shutil

from common.utility import safe_command


def remove_file(file_path):
    if not os.path.exists(file_path):
        return True

    if not os.path.isfile(file_path):
        return False

    try:
        os.remove(file_path)
        return True
    except:
        try:
            if os.name == 'nt':
                ret = os.system('del /f /a "%s"' % file_path)
            else:
                ret = os.system(safe_command('rm -f "%s"' % file_path))
            if ret == 0:
                return True
            else:
                return False
        except:
            return False


def remove_dir(dir_path):
    if not os.path.exists(dir_path):
        return True

    if not os.path.isdir(dir_path):
        return False

    try:
        shutil.rmtree(dir_path)
        return True
    except:
        try:
            if os.name == 'nt':
                ret = os.system('rd /s /q "%s"' % dir_path)
            else:
                ret = os.system(safe_command('rm -rf "%s"' % dir_path))
            if ret == 0:
                return True
            else:
                return False
        except:
            return False


def ensure_dir_exists(dir_path):
    if os.path.exists(dir_path) and os.path.isdir(dir_path):
        return

    if os.path.exists(dir_path) and os.path.isfile(dir_path):
        if not remove_file(dir_path):
            raise Exception("remove_file err: %s" % dir_path)

    try:
        os.makedirs(dir_path)
    except Exception as e:
        if e.errno != 17:  # 目录已经存在
            raise e


def ensure_dirs_exists(*dir_path_list):
    for dir_path in dir_path_list:
        ensure_dir_exists(dir_path)


def ensure_path_not_exists(path):
    if not os.path.exists(path):
        return

    if os.path.isfile(path):
        if not remove_file(path):
            raise Exception("remove_file err: %s" % path)
    elif os.path.isdir(path):
        if not remove_dir(path):
            raise Exception("remove_dir err: %s" % path)


def ensure_paths_not_exists(*path_list):
    for path in path_list:
        ensure_path_not_exists(path)


def ensure_empty_dirs_exists(*dir_path_list):
    for dir_path in dir_path_list:
        ensure_path_not_exists(dir_path)
        ensure_dir_exists(dir_path)


def copy_tree_files(src, dst, cover=False, skip=False, ignore_err=True):
    if not os.path.exists(dst):
        ensure_dirs_exists(dst)
    for src_file in yield_tree_files(src):
        need_copy = False
        dst_file = src_file.replace(src, dst, 1)
        if not os.path.exists(dst_file):
            ensure_dirs_exists(os.path.dirname(dst_file))
            need_copy = True
        elif not cover and not skip:
            raise Exception("dst file exists: %s" % dst_file)
        elif cover:
            need_copy = True
        if need_copy:
            try:
                shutil.copyfile(src_file, dst_file)
            except Exception as e:
                if not ignore_err:
                    raise e


def yield_tree_files(dir_path):
    if dir_path and os.path.isdir(dir_path):
        walker = os.walk(dir_path)
        for root, _, files in walker:
            for fileName in files:
                yield os.path.join(root, fileName)


def yield_tree_dirs(dir_path):
    if dir_path and os.path.isdir(dir_path):
        walker = os.walk(dir_path)
        for root, dirs, _ in walker:
            for dirName in dirs:
                yield os.path.join(root, dirName)
